package com.todo.event.activity.application.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.todo.common.utils.DateUtils;
import com.todo.common.utils.StringUtils;
import com.todo.component.redis.RedisService;
import com.todo.event.activity.application.core.engine.aviator.common.SignEnum;
import com.todo.event.activity.application.core.engine.aviator.function.InList;
import com.todo.event.activity.application.core.engine.aviator.function.NotinList;
import com.todo.event.activity.application.entity.bo.DecisionEventRuleBO;
import com.todo.event.activity.application.entity.context.FieldTransferContext;
import com.todo.event.activity.application.entity.model.DecisionRuleResultModel;
import com.todo.event.activity.application.handler.fieldtransfer.AbstractFieldTransferHandle;
import com.todo.event.activity.application.handler.fieldtransfer.FieldTransferFactory;
import com.todo.event.activity.common.base.EventKeyBuild;
import com.todo.event.activity.common.enums.EventFieldDataSourceEnum;
import com.todo.event.activity.common.enums.EventFieldTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author azhebuxing
 * @date 2025/1/13 23:32
 * @description
 */
@Slf4j
@Service
public class DecisionDataService {

    @Resource
    private FieldTransferFactory fieldTransferFactory;
    @Resource
    private RedisService redisService;

    /**
     * 事件决策规则校验
     *
     * @param decisionRule
     * @param payload
     * @param decisionId
     * @param eventCode
     * @return
     */
    public DecisionRuleResultModel eventDecisionRuleCheck(DecisionEventRuleBO decisionRule, JSONObject payload, Long decisionId, String eventCode) {
        DecisionRuleResultModel model = new DecisionRuleResultModel();
        if (payload == null) {
            log.warn("DecisionExecute#eventDecisionRuleCheck 事件基础校验完成，核心payload数据为空，默认失败，无法做规则判断 decisionId：【{}】eventCode：【{}】", decisionId, eventCode);
            model.setResult(false);
            model.setFailedReason("核心payload数据为空，无法做规则判断");
            return model;
        }
        if (decisionRule == null || (decisionRule.getGeneralRule() == null && CollectionUtils.isEmpty(decisionRule.getFieldRuleList()))) {
            log.info("DecisionExecute#eventDecisionRuleCheck 事件基础校验完成，不存在对应的规则配置，默认处理成功 decisionId：【{}】eventCode：【{}】", decisionId, eventCode);
            model.setResult(true);
            model.setFailedReason("不存在对应的规则配置，默认成功");
            return model;
        }
        if (StringUtils.isNotEmpty(decisionRule.getGeneralRule())) {
            //默认通用规则走QL
            AbstractFieldTransferHandle handle = fieldTransferFactory.getHandle(EventFieldDataSourceEnum.QLEXPRESS);
            FieldTransferContext generalContext = new FieldTransferContext();
            generalContext.setPayload(payload);
            generalContext.setTransfer(decisionRule.getGeneralRule());
            generalContext.setDataSource(EventFieldDataSourceEnum.QLEXPRESS);
            String result = handle.fieldTransfer(generalContext);
            if (!Boolean.parseBoolean(result)) {
                log.warn("DecisionExecute#eventDecisionRuleCheck 决策执行失败，通用规则校验失败， decisionId：【{}】eventCode：【{}】 generalContext:【{}】", decisionId, eventCode, JSONObject.toJSONString(generalContext));
                model.setResult(false);
                model.setFailedReason("决策执行失败，通用规则校验失败");
                model.setFailedReason(JSONObject.toJSONString(generalContext));
                return model;
            }
        }
        //基础的字段逻辑判断

        if (CollectionUtils.isNotEmpty(decisionRule.getFieldRuleList())) {
            List<String> fieldExpList = buildExpByFieldRule(decisionId, decisionRule.getFieldRuleList());
            if (CollectionUtils.isEmpty(fieldExpList)) {
                log.error("DecisionExecute#eventDecisionRuleCheck 决策规则执行失败，字段规则获取全部为空， decisionId：【{}】eventCode：【{}】", decisionId, eventCode);
                model.setResult(false);
                model.setFailedReason("字段规则获取全部为空");
                return model;
            }
            for (String fieldExp : fieldExpList) {
                //默认通用规则走AVIATOR
                AbstractFieldTransferHandle handle = fieldTransferFactory.getHandle(EventFieldDataSourceEnum.AVIATOR);
                FieldTransferContext generalContext = new FieldTransferContext();
                generalContext.setPayload(payload);
                generalContext.setTransfer(fieldExp);
                generalContext.setDataSource(EventFieldDataSourceEnum.AVIATOR);
                String result = handle.fieldTransfer(generalContext);
                if (!Boolean.parseBoolean(result)) {
                    log.warn("DecisionExecute#eventDecisionRuleCheck 决策执行失败，字段规则校验失败， decisionId：【{}】eventCode：【{}】 generalContext:【{}】", decisionId, eventCode, generalContext);
                    model.setResult(false);
                    model.setFailedReason("字段规则校验失败");
                    model.setFailedReason(JSONObject.toJSONString(generalContext));
                    return model;
                }
            }
        }
        model.setResult(true);
        return model;
    }

    private List<String> buildExpByFieldRule(Long decisionId, List<DecisionEventRuleBO.FieldRule> fieldRuleList) {
        if (CollectionUtils.isEmpty(fieldRuleList)) {
            return null;
        }
        String decisionFieldExpKey = EventKeyBuild.buildDecisionFieldExpKey(decisionId);
        if (redisService.hasKey(decisionFieldExpKey)) {
            return JSONObject.parseArray(redisService.get(decisionFieldExpKey), String.class);
        }
        //相同字段应该是 && 并且的关系
        Map<String, List<DecisionEventRuleBO.FieldRule>> fieldNameGroup = fieldRuleList.stream().collect(Collectors.groupingBy(DecisionEventRuleBO.FieldRule::getFieldName));
        List<String> result = new ArrayList<>();
        for (String key : fieldNameGroup.keySet()) {
            List<DecisionEventRuleBO.FieldRule> fieldRuleListByFieldName = fieldNameGroup.get(key);
            if (CollectionUtils.isEmpty(fieldRuleListByFieldName)) {
                continue;
            }
            StringBuilder expSB = new StringBuilder();
            int loopCount = 0;
            for (DecisionEventRuleBO.FieldRule fieldRule : fieldRuleListByFieldName) {
                loopCount++;
                expSB.append(" ")
                        .append(buildFieldExp(fieldRule))
                        .append(" ");
                if (loopCount != fieldRuleListByFieldName.size()) {
                    expSB.append(" ").append(SignEnum.DAND.getVal()).append(" ");
                }
            }
            result.add(expSB.toString());
        }
        if (CollectionUtils.isNotEmpty(result)) {
            redisService.set8H(decisionFieldExpKey, JSONObject.toJSONString(result));
        }
        return result;
    }

    private String buildFieldExp(DecisionEventRuleBO.FieldRule fieldRule) {
        StringBuilder sb = new StringBuilder();
        switch (fieldRule.getOperateEnum()) {
            case GT:
            case NEQ:
            case LT:
            case GTOE:
            case EQ:
            case LTOE:
                return sb.append(fieldRule.getFieldName())
                        .append(" ")
                        .append(fieldRule.getOperateEnum().getCode())
                        .append(" ")
                        .append(buildAviatorValue(fieldRule.getTypeEnum(), fieldRule.getOperateValue()))
                        .toString();
            case IN:
                return InList.buildInListExp(fieldRule.getFieldName(), String.valueOf(buildAviatorValue(fieldRule.getTypeEnum(), fieldRule.getOperateValue())), ",");
            case NOT_IN:
                return NotinList.buildInListExp(fieldRule.getFieldName(), String.valueOf(buildAviatorValue(fieldRule.getTypeEnum(), fieldRule.getOperateValue())), ",");
            default:
                return "1 == 1";
        }
    }

    private Object buildAviatorValue(EventFieldTypeEnum fieldTypeEnum, String operateValue) {
        switch (fieldTypeEnum) {
            case STRING:
                return "'" + operateValue + "'";
            case LONG:
                return Long.parseLong(operateValue);
            case DOUBLE:
                return Double.parseDouble(operateValue);
            //array 类型的操作，aviator 处理字符串数据 例如 [1,2,3,4] 判断逻辑为 处理 x in 1,2,3,4
            case ARRAY:
                return JSONObject.parseArray(operateValue).stream()
                        .map(Object::toString)
                        .collect(Collectors.joining(","));
            case BOOLEAN:
                return Boolean.parseBoolean(operateValue);
            case DATE:
                return DateUtils.dateTime(operateValue, DateUtils.YYYY_MM_DD_HH_MM_SS);
            case DECIMAL:
                return new BigDecimal(operateValue);
            case OBJECT:
                return JSONObject.parseObject(operateValue);
            default:
                return operateValue;
        }
    }
}
